package com.ml.loan.common.utils;

import cn.hutool.core.date.LocalDateTimeUtil;

import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.Date;

public enum DateTimeUtil {
    //

    INSTANCE;

    public static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern("HHmmss");
    public static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyyMMdd");
    public static final DateTimeFormatter DATE_HYPHEN_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");
    public static final DateTimeFormatter DATETIME_FORMATTER = DateTimeFormatter.ofPattern("yyyyMMdd HH:mm:ss");
    public static final DateTimeFormatter TIMESTAMP_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    /**
     * 获取当前系统时间
     *
     * @return
     */
    public LocalTime getLocalTime() {
        return LocalTime.now();
    }

    /**
     * 获取当前系统日期
     *
     * @return
     */
    public LocalDate getLocalDate() {
        return LocalDate.now();
    }

    /**
     * 获取当前系统日期时间
     *
     * @return
     */
    public LocalDateTime getLocalDateTime() {
        return LocalDateTime.now();
    }


    /**
     * 今日起始时间 ：20xx-MM-dd 00:00:00
     *
     * @return
     */
    public static String getTodayStartTimeString() {
        return TIMESTAMP_FORMATTER.format(LocalDateTime.of(LocalDate.now(), LocalTime.MIN));
    }

    /**
     * 今日结束时间：20xx-MM-dd 23:59:59
     *
     * @return
     */
    public String getTodayEndTimeString() {
        return TIMESTAMP_FORMATTER.format(LocalDateTime.of(LocalDate.now(), LocalTime.MAX));
    }

    /**
     * 获取当前系统时间字符串
     *
     * @return
     */
    public String getLocalTimeString() {
        return LocalTime.now().format(TIME_FORMATTER);
    }

    /**
     * 获取当前系统日期字符串
     *
     * @return
     */
    public String getLocalDateString() {
        return LocalDate.now().format(DATE_FORMATTER);
    }

    /**
     * 获取当前系统日期时间字符串
     *
     * @return
     */
    public String getLocalDateTimeString() {
        return LocalDateTime.now().format(DATETIME_FORMATTER);
    }

    public String getLocalDateTimeStampString() {
        return LocalDateTime.now().format(TIMESTAMP_FORMATTER);
    }

    /**
     * 字符串转LocalTime
     *
     * @param time
     * @return
     */
    public LocalTime string2LocalTime(String time) {
        return LocalTime.parse(time, TIME_FORMATTER);
    }

    /**
     * 字符串转LocalDate
     *
     * @param date
     * @return
     */
    public LocalDate string2LocalDate(String date) {
        return LocalDate.parse(date, DATE_FORMATTER);
    }

    /**
     * 字符串转LocalDateTime
     *
     * @param dateTime
     * @return
     */
    public LocalDateTime string2LocalDateTime(String dateTime) {
        return LocalDateTime.parse(dateTime, DATETIME_FORMATTER);
    }

    /**
     * Date转LocalDateTime
     *
     * @param date
     * @return
     */
    public LocalDateTime date2LocalDateTime(Date date) {
        Instant instant = date.toInstant();//An instantaneous point on the time-line.(时间线上的一个瞬时点。)
        ZoneId zoneId = ZoneId.systemDefault();//A time-zone ID, such as {@code Europe/Paris}.(时区)
        LocalDateTime localDateTime = instant.atZone(zoneId).toLocalDateTime();
        return localDateTime;
    }

    /**
     * Date转LocalDate
     *
     * @param date
     * @return
     */
    public LocalDate date2LocalDate(Date date) {
        Instant instant = date.toInstant();//An instantaneous point on the time-line.(时间线上的一个瞬时点。)
        ZoneId zoneId = ZoneId.systemDefault();//A time-zone ID, such as {@code Europe/Paris}.(时区)
        LocalDate localDate = instant.atZone(zoneId).toLocalDate();
        return localDate;
    }

    /**
     * Date转LocalDate
     *
     * @param date
     * @return
     */
    public LocalTime date2LocalTime(Date date) {
        Instant instant = date.toInstant();//An instantaneous point on the time-line.(时间线上的一个瞬时点。)
        ZoneId zoneId = ZoneId.systemDefault();//A time-zone ID, such as {@code Europe/Paris}.(时区)
        LocalTime localTime = instant.atZone(zoneId).toLocalTime();
        return localTime;
    }

    /**
     * LocalDateTime转换为Date
     *
     * @param localDateTime
     */
    public Date localDateTime2Date(LocalDateTime localDateTime) {
        ZoneId zoneId = ZoneId.systemDefault();
        ZonedDateTime zdt = localDateTime.atZone(zoneId);//Combines this date-time with a time-zone to create a  ZonedDateTime.
        Date date = Date.from(zdt.toInstant());
        return date;
    }

    /**
     * 自定义HH:mm:ss获取LocalDateTime
     */
    public LocalDateTime getLocalDateTimeZero(String times) {
        DateTimeFormatter dtf2 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        LocalDate data = LocalDate.now();
        DateTimeFormatter dtf3 = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        String strDate3 = dtf3.format(data);
        strDate3 = strDate3 + times;
        LocalDateTime time1 = LocalDateTime.parse(strDate3, dtf2);
        return time1;
    }

    /**
     * 获取下一年 的localdateTime
     */
    public LocalDateTime getLocalDateTimeNextYear() {
        DateTimeFormatter dtf2 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        LocalDate data = LocalDate.now().plusYears(1);
        DateTimeFormatter dtf3 = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        String strDate3 = dtf3.format(data);
        strDate3 = strDate3 + " 23:59:59";
        LocalDateTime time1 = LocalDateTime.parse(strDate3, dtf2);
        return time1;
    }

    /**
     * 字符串转LocalDateTime
     *
     * @param dateTime
     * @return
     */
    public LocalDateTime stringToLocalDateTime(String dateTime) {
        return LocalDateTime.parse(dateTime, TIMESTAMP_FORMATTER);
    }

    /**
     * 计算两个时间点的天数差
     *
     * @param dt1 第一个时间点
     * @param dt2 第二个时间点
     * @return int，即要计算的天数差
     */
    public int dateDiff(LocalDateTime dt1, LocalDateTime dt2) {
        //获取第一个时间点的时间戳对应的秒数
        long t1 = dt1.toEpochSecond(ZoneOffset.ofHours(0));
        //获取第一个时间点在是1970年1月1日后的第几天
        long day1 = t1 / (60 * 60 * 24);
        //获取第二个时间点的时间戳对应的秒数
        long t2 = dt2.toEpochSecond(ZoneOffset.ofHours(0));
        //获取第二个时间点在是1970年1月1日后的第几天
        long day2 = t2 / (60 * 60 * 24);
        //返回两个时间点的天数差
        return (int) (day2 - day1);
    }

    /**
     * 计算两个时间点的天数差
     *
     * @param dt1   第一个时间点
     * @param dt2   第二个时间点
     * @param isAbs 是否取绝对值
     * @return int，即要计算的天数差
     */
    public int dateDiff(LocalDateTime dt1, LocalDateTime dt2, boolean isAbs) {
        //获取第一个时间点的时间戳对应的秒数
        long t1 = dt1.toEpochSecond(ZoneOffset.ofHours(0));
        //获取第一个时间点在是1970年1月1日后的第几天
        long day1 = t1 / (60 * 60 * 24);
        //获取第二个时间点的时间戳对应的秒数
        long t2 = dt2.toEpochSecond(ZoneOffset.ofHours(0));
        //获取第二个时间点在是1970年1月1日后的第几天
        long day2 = t2 / (60 * 60 * 24);
        //返回两个时间点的天数差
        return isAbs ? (int) Math.abs(day2 - day1) : (int) (day2 - day1);
    }


    /**
     * 统计代码耗时
     *
     * @param start
     * @author caozx
     * @date 2021/4/8 18:26
     **/
    public long diffMs(long start) {
        return System.currentTimeMillis() - start;
    }

    /**
     * 时间戳距现在的时间
     *
     * @param timestamp
     * @param unit
     * @author caozx
     * @date 2021/4/20 18:20
     **/
    public long betweenByTimestamp(long timestamp, ChronoUnit unit) {
        LocalDateTime localDateTime = Instant.ofEpochMilli(timestamp).atZone(ZoneOffset.ofHours(8)).toLocalDateTime();
        Duration duration = LocalDateTimeUtil.between(localDateTime, LocalDateTime.now());
        long between = 0;
        switch (unit) {
            case DAYS:
                //天
                between = duration.toDays();
                break;
            case HOURS:
                //小时
                between = duration.toHours();
                break;
            case MINUTES:
                //分钟
                between = duration.toMinutes();
                break;
            case MILLIS:
                //毫秒
                between = duration.toMillis();
                break;
            case NANOS:
                //纳秒
                between = duration.toNanos();
                break;
            default:
                between = 0;
                break;
        }
        return Math.abs(between);
    }
}
